#include "app_buffer.h"
#include <stdlib.h>
#include <string.h>
#include "thirdparty/log/log.h"

static pthread_mutex_t lock_initializer = PTHREAD_MUTEX_INITIALIZER;

int app_buffer_init(Buffer *buffer, int n)
{
    if (buffer->ptr)
    {
        log_warn("Buffer already initialized");
        return -1;
    }

    buffer->ptr = malloc(n);
    if (!buffer->ptr)
    {
        log_warn("Not enough memory for buffer");
        return -1;
    }

    memcpy(&buffer->lock, &lock_initializer, sizeof(pthread_mutex_t));
    buffer->size = n;
    buffer->start = 0;
    buffer->len = 0;
    log_trace("Buffer %p created", buffer);
    return 0;
}

void app_buffer_free(Buffer *buffer)
{
    if (buffer->ptr)
    {
        free(buffer->ptr);
        buffer->ptr = NULL;
    }
    log_trace("Buffer %p freed", buffer);
}

int app_buffer_read(Buffer *buffer, void *buf, int len)
{

    if (!buffer || !buf)
    {
        log_warn("Buffer or buf not valid");
        return -1;
    }

    if (len < 0)
    {
        log_warn("Len not valid");
        return -1;
    }

    pthread_mutex_lock(&buffer->lock);
    // 首先计算实际读取长度
    len = buffer->len < len ? buffer->len : len;

    // 如果len为0
    if (len == 0)
    {
        pthread_mutex_unlock(&buffer->lock);
        return 0;
    }

    // 判断数据需要拷贝一次还是两次
    if (buffer->start + len > buffer->size)
    {
        // 拷贝两次
        int first_len = buffer->size - buffer->start;
        memcpy(buf, buffer->ptr + buffer->start, first_len);
        memcpy(buf + first_len, buffer->ptr, len - first_len);
        buffer->start = len - first_len;
    }
    else
    {
        // 拷贝一次
        memcpy(buf, buffer->ptr + buffer->start, len);
        buffer->start += len;
    }

    buffer->len -= len;

    pthread_mutex_unlock(&buffer->lock);

    log_trace("Buffer %p status: start %d, len %d", buffer, buffer->start, buffer->len);

    return len;
}

int app_buffer_write(Buffer *buffer, void *buf, int len)
{
    if (!buffer || !buf)
    {
        log_warn("Buffer or buf not valid");
        return -1;
    }

    if (len < 0)
    {
        log_warn("Len not valid");
        return -1;
    }

    pthread_mutex_lock(&buffer->lock);
    // 首先判断能不能写下
    if (buffer->size - buffer->len < len)
    {
        pthread_mutex_unlock(&buffer->lock);
        log_warn("Buffer %p not enough for len %d", buffer, len);
        return -1;
    }

    // 首先需要找到写的起始offset
    int write_offset = buffer->start + buffer->len;
    if (write_offset > buffer->size)
    {
        write_offset -= buffer->size;
    }

    // 判断写一次还是写两次
    if (len + write_offset > buffer->size)
    {
        // 写两次
        int first_len = buffer->size - write_offset;
        memcpy(buffer->ptr + write_offset, buf, first_len);
        memcpy(buffer->ptr, buf + first_len, len - first_len);
    }
    else
    {
        // 写一次
        memcpy(buffer->ptr + write_offset, buf, len);
    }

    buffer->len += len;
    pthread_mutex_unlock(&buffer->lock);

    log_trace("Buffer %p status: start %d, len %d", buffer, buffer->start, buffer->len);

    return 0;
}
